package flex.cc.single.service.impl;

import java.util.Base64;
import java.util.Date;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import com.alibaba.fastjson.JSONObject;

import flex.cc.PublicUtil;
import flex.cc.common.utils.CommonUtils;
import flex.cc.common.utils.HttpClientUtil;
import flex.cc.drive.util.DriveDESUtil;
import flex.cc.single.dao.SingleCouponTrackDao;
import flex.cc.single.dao.SingleOrderDao;
import flex.cc.single.dao.SingleRecordDao;
import flex.cc.single.dto.entity.SingleCouponTrackEntity;
import flex.cc.single.dto.entity.SingleOrderEntity;
import flex.cc.single.dto.entity.SingleRecordEntity;
import flex.cc.single.service.DispenseSingleCouponService;
import flex.cc.single.util.SingleSignUtil;
import flex.cc.store.dao.StoreCouponDao;
import flex.cc.store.dto.entity.StoreCouponEntity;
import flex.cc.system.dao.DictCodeDao;
import flex.cc.system.entity.DictCodeEntity;
import flex.cc.util.APIConfigUtil;
import flex.cc.util.DateUtil;

/**
*
* @author R
* @2022年3月31日  19:52:51
* @desc 发券业务流程实现层
*/
@Service("signDispenseSingleCouponService")
@Transactional(rollbackFor = Exception.class)
public class DispenseSingleCouponServiceImpl implements DispenseSingleCouponService {
    private static final Logger logger = LoggerFactory.getLogger(DispenseSingleCouponServiceImpl.class);
    @Autowired
	private APIConfigUtil apiConfigUtil;
    @Autowired
    private DictCodeDao dictCodeDao;
    @Autowired
    private SingleOrderDao singleOrderDao;
    @Autowired
    private SingleRecordDao singleRecordDao;
    @Autowired
    private StoreCouponDao storeCouponDao;
    @Autowired
    private SingleCouponTrackDao singleCouponTrackDao;
    /**
     * @description 发券接口相关业务处理
     * @param requestBodyMap 发券接口请求体
     * @return
     * @exception/throws
    */
	@Override
	public JSONObject dispenseSingleCoupon(Map<String, Object> requestBodyMap) {
		JSONObject jsonResult = new JSONObject();
		Map<String, Object> dataMap = new HashMap<String, Object>();
		Map<String, Object> requestMap = new HashMap<String, Object>();
		try {
			//获取请求ID
			String id = PublicUtil.isNotEmpty(requestBodyMap.get("id")) ? requestBodyMap.get("id").toString() : null; 
			dataMap.put("order", id);
			
			
			String key = apiConfigUtil.getSingleApiConfig("encryptKey");
			String key3Des = apiConfigUtil.getSingleApiConfig("key3Des");
			String signKey = apiConfigUtil.getSingleApiConfig("signKey");
			String apiSource = apiConfigUtil.getSingleApiConfig("apiSource");
			String createOrderUrl = apiConfigUtil.getSingleApiConfig("createOrderUrl");
			String provider = apiConfigUtil.getSingleApiConfig("provider");
			//域名
			String realmName = apiConfigUtil.getSingleApiConfig("realmName");
			//获取UserCard对象
			String userCard = PublicUtil.isNotEmpty(requestBodyMap.get("UserCard")) ? requestBodyMap.get("UserCard").toString() : null; 
			//获取签名
			String sign = PublicUtil.isNotEmpty(requestBodyMap.get("sign")) ? requestBodyMap.get("sign").toString() : null; 
			logger.info("报文中的签名："+sign);
			//进行验签操作
			if(sign==null){
	    		jsonResult.put("resultCode", "01");
	    		jsonResult.put("resultDesc", "签名为空，无法进行验签");
	            return jsonResult;
			}
			boolean flag = SingleSignUtil.isSignatureValid(requestBodyMap,signKey);
			if(!flag){
	    		jsonResult.put("resultCode", "01");
	    		jsonResult.put("resultDesc", "验签失败");
	            return jsonResult;
			}
			dataMap.put("sourceCode", apiSource);
	        dataMap.put("orgSource", apiSource);
			//解析UserCard对象
	        JSONObject userCardJsonObj = JSONObject.parseObject(userCard);
        	Map<String, Object>  userCardBodyMap = userCardJsonObj.toJavaObject(Map.class);
	        
	        //获取客户号
	        String customerCode = PublicUtil.isNotEmpty(userCardBodyMap.get("customerCode")) ? userCardBodyMap.get("customerCode").toString() : null;
	        //获取卡券类型  
	        String activityCode = PublicUtil.isNotEmpty(userCardBodyMap.get("cardType")) ? userCardBodyMap.get("cardType").toString() : null;
	        dataMap.put("activityType", activityCode);
	        
	        //渠道
	    	String channel = PublicUtil.isNotEmpty(requestBodyMap.get("apiSource")) ? requestBodyMap.get("apiSource").toString() : null;;
	    	
	        Map<String, Object> params = new HashMap<String, Object>();
	        params.put("typeCode", "singleActivityName");
	        params.put("code", activityCode);
	        List<DictCodeEntity> dictCodeEntityList = dictCodeDao.queryDictCodeListByParams(params);
	        String serviceType = "";
	        if(dictCodeEntityList!=null&&dictCodeEntityList.size()>0){
	        	DictCodeEntity dictCodeEntity = dictCodeEntityList.get(0);
	        	serviceType = dictCodeEntity.getValue2();
	        }
	        
	        //获取失效期
	        String expireTime = PublicUtil.isNotEmpty(userCardBodyMap.get("expireTime")) ? userCardBodyMap.get("expireTime").toString() : null;
	        
	        dataMap.put("endTime", DateUtil.transferFormat(expireTime));
	        //获取生效期
	        String startTime = PublicUtil.isNotEmpty(userCardBodyMap.get("startTime")) ? userCardBodyMap.get("startTime").toString() : null;
			
	        //上游未传递客户手机号码 商定后默认手机号码
	        dataMap.put("phoneNum", "13111111111");
	        
	        JSONObject dateJsonObj=new JSONObject(dataMap);
	        //加密请求报文
			String encryptDateStr = DriveDESUtil.driverEncrypt(dateJsonObj.toString(), key,key3Des);
			requestMap.put("encryptJsonStr", encryptDateStr);
			JSONObject requestJsonObj=new JSONObject(requestMap);

			Date requestDate = new Date();
	        //调用下单接口
	    	String packageResult = HttpClientUtil.sendHttpPost(createOrderUrl, requestJsonObj.toString(), new HashMap<String, String>(){{
	            put("Content-Type", "application/json;charset=UTF-8");
	        }});
	    	Date responseDate = new Date();
	    	JSONObject resultObject = JSONObject.parseObject(packageResult);
	    	Map<String, Object> responseBodyMap = resultObject.toJavaObject(Map.class);
	    	//响应码
	    	String resultCode = (String) responseBodyMap.get("resultCode");
	    	//加密串
	    	String encryptJsonStr = (String) responseBodyMap.get("encryptJsonStr");
	    	//结果描述
	    	String resultDes = (String) responseBodyMap.get("resultDes");
	    	
	    	SingleRecordEntity singleRecordEntity = new SingleRecordEntity();
	    	singleRecordEntity.setOrderNo(id);
	    	singleRecordEntity.setInterfaceName("发券接口");
	    	singleRecordEntity.setRequestTime(requestDate);
	    	singleRecordEntity.setRequestEncryptBody(requestJsonObj.toString());
	    	singleRecordEntity.setRequestBody(dateJsonObj.toString());
	    	singleRecordEntity.setResponseEncryptBody(packageResult);
	    	singleRecordEntity.setResponseTime(responseDate);
	    	singleRecordEntity.setCreateTime(new Date());
	    	
	    	if(resultCode.equals("SUCCESS")){
	    		//解析加密串
	    		String jsonStr = DriveDESUtil.driverDecrypt(encryptJsonStr, key, key3Des);
	    		JSONObject jsonStrObject = JSONObject.parseObject(jsonStr);
		    	Map<String, Object> jsonStrMap = jsonStrObject.toJavaObject(Map.class);
		    	//获取卡券编码
		    	String orderCode = (String) jsonStrMap.get("orderCode");
		    	//获取订单二维码
		    	String orderEncrypt = (String) jsonStrMap.get("orderEncrypt");
		    	
		    	singleRecordEntity.setOrderId(orderCode);
		    	singleRecordEntity.setStatus("1");
		    	singleRecordEntity.setRemark("发券接口请求成功");
		    	
		    	Map<String, Object> bodyMap = new HashMap<String, Object>();
		    	bodyMap.put("orderCode", orderCode);
		    	Map<String, Object> subbodyMap = new HashMap<String, Object>();
		    	subbodyMap.put("orderCode", orderCode);
		    	subbodyMap.put("orderEncrypt", orderEncrypt);
		    	JSONObject subbodyObj=new JSONObject(subbodyMap);
		    	bodyMap.put("encryptJsonStr", subbodyObj.toString());
		    	JSONObject bodyObj=new JSONObject(bodyMap);
		    	singleRecordEntity.setResponseBody(bodyObj.toString());
		    	singleRecordDao.insertVo(singleRecordEntity);
		    	
		    	
		    	//保存服务单表信息
		    	SingleOrderEntity singleOrderEntity = new SingleOrderEntity();
		    	singleOrderEntity.setOrderId(orderCode);
		    	singleOrderEntity.setOrderNo(id);
		    	singleOrderEntity.setCustomerCode(customerCode);
		    	singleOrderEntity.setActivityId(activityCode);
		    	singleOrderEntity.setServiceType(serviceType);
		    	singleOrderEntity.setIsDelete(0);
		    	singleOrderEntity.setCreateTime(new Date());
		    	singleOrderEntity.setCreater("system");
		    	singleOrderEntity.setUpdateTime(new Date());
		    	singleOrderEntity.setUpdater("system");
		    	singleOrderDao.insert(singleOrderEntity);
		    	
		    	//保存卡券信息
		    	StoreCouponEntity storeCouponEntity = new StoreCouponEntity();
		    	storeCouponEntity.setCouponNum(orderCode);
		    	storeCouponEntity.setActivityId(activityCode);
		    	storeCouponEntity.setEncrypt(orderEncrypt);
		    	
		    	//卡券状态  根据生效日期 和失效日期判断是否生效或者失效
		    	Date currentTime = new Date();
		    	//生效日期
		    	Date couponEffTime = DateUtil.stringToDate(startTime+" 00:00:00", "yyyy-MM-dd HH:mm:ss");
				storeCouponEntity.setEffDate(couponEffTime);
		    	
		    	//失效日期
		    	Date couponExpTime = DateUtil.stringToDate(expireTime+" 23:59:59", "yyyy-MM-dd HH:mm:ss");
		    	storeCouponEntity.setExpDate(couponExpTime);
		    	
		    	if(currentTime.compareTo(couponEffTime)<0){
		    		//待生效
		    		storeCouponEntity.setStatus("0");
		    	}
		    	if(couponEffTime.compareTo(currentTime)<0&&currentTime.compareTo(couponExpTime)<0){
		    		//生效
		    		storeCouponEntity.setStatus("1");
		    	}
		    	if(couponExpTime.compareTo(currentTime)<0){
		    		//失效
		    		storeCouponEntity.setStatus("2");
		    	}
				//渠道方
				storeCouponEntity.setChannel(channel);
				//一期写死，后期根据配置信息取
				storeCouponEntity.setServer(provider);
				//归属订单
				storeCouponEntity.setOrderId(id);
		    	storeCouponEntity.setIsDelete(0);
		    	storeCouponEntity.setCreateTime(new Date());
		    	storeCouponEntity.setCreater("system");
		    	storeCouponEntity.setUpdateTime(new Date());
		    	storeCouponEntity.setUpdater("system");
		    	storeCouponDao.insert(storeCouponEntity);
		    	
		    	
		    	//返回上游成功报文
		    	jsonResult.put("resCode", "SUCCESS");
	    		jsonResult.put("resultDesc", "请求发券接口成功");
	    		jsonResult.put("id", orderCode);
	    		saveTrack(storeCouponEntity, "2", "请求发券接口成功", "1", "下游发券接口");
	    		
	    		Map<String, Object> body = new HashMap<String, Object>();
	    		body.put("couponNum", orderCode);
	    		body.put("activityId", activityCode);
	    		String json = CommonUtils.toJSONString(body);
	    		byte[] bytes = json.getBytes();
	        	String paramsStr = Base64.getEncoder().encodeToString(bytes);
	        	
	        	
	    		jsonResult.put("url", realmName+"/#/single/common?params="+paramsStr);
	            return jsonResult;
		    	
	    	}else{
	    		logger.info("请求发券接口失败");
		    	singleRecordEntity.setStatus("0");
		    	singleRecordEntity.setRemark("发券接口请求失败，失败原因："+resultDes);
		    	singleRecordDao.insertVo(singleRecordEntity);
				jsonResult.put("resCode", "FAILURE");
	    		jsonResult.put("resultDesc", "请求发券接口失败");
	    		jsonResult.put("id", "");
	            return jsonResult;
	    	}
		}catch (Exception e) {
			logger.info("请求下单接口异常"+e.getMessage());
			jsonResult.put("resCode", "FAILURE");
    		jsonResult.put("resultDesc", "请求下单接口异常");
    		jsonResult.put("id", "");
            return jsonResult;
		}
	}
	
	/**
	 * 新增卡券使用轨迹
	 * @param couponEntity  卡券信息
	 * @param trackType 轨迹类型：0-车服内部，1-与上游交互，2-与下游交互，3-与商户端交互
	 * @param trackDesc 轨迹描述
	 * @param result 接口请求结果：0-失败，1-成功
	 * @param creater
	 */
	 private void saveTrack(StoreCouponEntity couponEntity, String trackType, String trackDesc, String result, String creater){
		 Date d = new Date();
		 SingleCouponTrackEntity vo = new SingleCouponTrackEntity(couponEntity.getId(),couponEntity.getCouponNum(),
				 trackType,trackDesc,couponEntity.getStatus(),result);
		 vo.setIsDelete(0);
		 vo.setCreateTime(d);
		 vo.setCreater(creater);
		 vo.setUpdateTime(d);
		 vo.setUpdater(creater);
		 singleCouponTrackDao.insert(vo);	        
	 }
}
